/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/

#if !defined(AFX_GFXINTERFACE_H__287E3BC9_0E37_4D0B_87B2_4EA1CEF0A76D__INCLUDED_)
#define AFX_GFXINTERFACE_H__287E3BC9_0E37_4D0B_87B2_4EA1CEF0A76D__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <math.h>
#include <tchar.h>
#include <objbase.h>

// del [5/8/2009 JYB]
// #ifndef max
// 	#define max(a,b) ((a) > (b) ? (a) : (b))
// #endif
// #ifndef min
// 	#define min(a,b) ((a) < (b) ? (a) : (b))
// #endif
#include <gdiplus.h>
// #ifdef max
// 	#undef max
// #endif
// 
// #ifdef min
// 	#undef min
// #endif
// 
#include <pgl/igfx/STLIGfx.h>
#include <pgl/algotools/AlgoTools.h>

#define IGFX_PI 3.141592653589
/*
#ifndef _GFXINTERFACE_LIB
#ifndef _GFXINTERFACE_LIB_LOADED
#define _GFXINTERFACE_LIB_LOADED

		#if _MSC_VER >= 1300
			#ifdef _DEBUG
				#ifdef _UNICODE
					#pragma message("     _Adding library: IGfx8ud.lib: MFC8.0, dll, Debug, UNICODE" ) 
					#pragma comment(lib, "IGfx8ud.lib")
				#else
					#pragma message("     _Adding library: IGfx8d.lib: MFC8.0, dll,  Debug, MBCS" ) 
					#pragma comment(lib, "IGfx8d.lib")
				#endif
			#else
				#ifdef _UNICODE
					#pragma message("     _Adding library: IGfx8u.lib: MFC8.0, dll,  Release, UNICODE" ) 
					#pragma comment(lib, "IGfx8u.lib")
				#else
					#pragma message("     _Adding library: IGfx7.lib: MFC8.0,  dll, Release, MBCS" ) 
					#pragma comment(lib, "IGfx8.lib")
				#endif
			#endif
		#else
			#ifdef _DEBUG
				#ifdef _UNICODE
					#pragma message("     _Adding library: IGfxud.lib: MFC4.2, dll,  Debug, UNICODE" ) 
					#pragma comment(lib, "IGfxud.lib")
				#else
					#pragma message("     _Adding library: IGfxd.lib: MFC4.2,  dll, Debug, MBCS" ) 
					#pragma comment(lib, "IGfxd.lib")
				#endif
			#else
				#ifdef _UNICODE
					#pragma message("     _Adding library: IGfxu.lib: MFC4.2, dll,  Release, UNICODE" ) 
					#pragma comment(lib, "IGfxu.lib")
				#else
					#pragma message("     _Adding library: IGfx.lib: MFC4.2, dll,  Release, MBCS" ) 
					#pragma comment(lib, "IGfx.lib")
				#endif
			#endif
		#endif
#endif
#endif
		*/

/*!
	\defgroup IGfxGroup Multiple Graphic Interface : IGfx
*/

/*! \namespace gfxinterface

  \ingroup IGfxGroup
  Namespace of the library.
*/
namespace gfxinterface
{
/*!
	\defgroup IGfxStruct Structures and Enumerations
	\ingroup IGfxGroup
*/
/*! \struct SRGBA 
	\ingroup IGfxStruct
\brief A RGBA color structure. 
*/
typedef struct _sRGBA
{
	_sRGBA(double _r=1,double _g=1,double _b=1, double _a=1){	r=_r;g=_g;b=_b;a=_a;};
	//! current red value
	double r;
	//! current green value
	double g;
	//! current blue value
	double b;
	//! current alpha value
	double a;
} SRGBA;

/* \struct SRectF

  \ingroup IGfxStruct
\brief A rect (left, right, bottom, top) structure, double version
*/
typedef struct _sRectD
{
	double left;
	double top;
	double width;
	double height;
} SRectD;

/* \struct SRectI

  \ingroup IGfxStruct
\brief A rect (left, right, bottom, top) structure, int version
*/
typedef struct _sRectI
{
	int left;
	int top;
	int width;
	int height;
} SRectI;

/* \class SPointD

  \ingroup IGfxStruct
\brief A point (x,y) (x,y are doubles)
*/
typedef struct _sPointD
{
	_sPointD( double _x=0, double _y=0){x=_x; y=_y;};
	double x;
	double y;
} SPointD;


/* \struct RectFList

\ingroup IGfxStruct
\brief A list of SRectF structure
\sa std::list
*/
typedef std::stack<SRectD> SRectDStack;


/* \enum Rect drawing type

\ingroup IGfxStruct
*/
typedef enum _ERectType
{
	RectTypeFilled =				0x0001,
	RectTypeNoContour =				0x0002,
	RectTypeShadowLowerLeft =		0x0004,
	RectTypeShadowLowerRight =		0x0008,
	RectTypeShadowUpperLeft =		0x0010,
	RectTypeShadowUpperRight =		0x0020,
	RectTypeSoftShadowLowerLeft =	0x0040,
	RectTypeSoftShadowLowerRight =	0x0080,
	RectTypeSoftShadowUpperLeft =	0x0100,
	RectTypeSoftShadowUpperRight =	0x0200
} ERectType;

/* \enum Text Alignment

\ingroup IGfxStruct
*/
typedef enum _ETextAlignment
{
	TextAlignmentLeft=		0x0001,
	TextAlignmentRight=		0x0002,
	TextAlignmentCenter=	0x0004,
} ETextAlignment;

/* \enum Arc type enumeration

\ingroup IGfxStruct
*/
typedef enum _EArcType
{
	ArcTypeContour =	0x0001,
	ArcTypeFill =		0x0002,
	ArcTypeExploded =	0x0004,
}	EArcType;

/* \enum Line type enumeration

\ingroup IGfxStruct
*/
typedef enum _ELineType
{
	LineTypeClosed =		0x0001,
	LineTypeNoContour =		0x0002,
	LineTypeFilled =		0x0004,
	LineTypeSnapBottom =	0x0008,
	LineTypeShadow =		0x0010
} ELineType;

/* \enum Band type enumeration

\ingroup IGfxStruct
*/
typedef enum _EBandType
{
	BandTypeLowerLineOnly=		0x0001,
	BandTypeUpperLowerLine =	0x0002,
	BandTypeFullContour =		0x0004,
	BandTypeNoContour =			0x0008,
	BandTypeNotFilled =			0x0010,
	BandTypeAbsolute =			0x0020,
	BandTypeLineShadow =		0x0040
} EBandType;

/* \enum Available layers

There are 2 layers for objects:
	- back, static drawing,
	- front, dynamic drawing
	- disabled, disables layer mode.

\ingroup IGfxStruct
*/
typedef enum _ELayer
{
	//! disabling layers
	LayerDisabled = 0,
	//! back
	LayerBack = 1,
	//! in front
	LayerFront = 2
} ELayer;


/*! \enum ETextureWrapMode
\ingroup IGfxStruct
*/
typedef enum _ETextureWrapMode
{
	//! Tiling without flipping
	TexWrapModeTile=1,
	//! Tiles are flipped horizontally as you move from one tile to the next in a row
	TexWrapModeTileFlipX=2,
	//! Tiles are flipped vertically as you move from one tile to the next in a column
	TexWrapModeTileFlipY=3,
	//! Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column
	TexWrapModeTileFlipXY=4,
	//! No tiling takes place
	TexWrapModeClamp=5
} ETextureWrapMode;

enum EStockType
{
	StockTypeCandleStick=1,
	StockTypeOpenHighLow=2,
	StockTypeOpenHighLowClose=3
};

#ifndef GFX_ADDCOMMENT
	#ifdef _DEBUG
		#define GFX_ADDCOMMENT(gfx , comment ) gfx.AddComment(_T(comment))
	#else
		#define GFX_ADDCOMMENT(gfx , comment )
	#endif
#endif

/*! \brief Virtual base class for graphic interfaces

\ingroup IGfxGroup

This class contains the definitions of the functions that inherited classes must implement.
*/
class CGfxInterface
{
protected:
	//! Bounding box state.
	struct SBBoxState
	{
		SRectI screen;
		SRectD world;
	};

	//! A list of SRectF structure
	typedef std::stack<SBBoxState> SBBoxStateStack;

public:
	//!  \name Render flags
	//@{
	/*! Rendering options (anti aliasing, and others)

	These options are just indication. They are taken into account if the device supports them.
	*/
	static enum ERenderOption
	{
		//! No text antialiasing
		RenderOptionNoTextAntiAlias =			0x0001,
		//! No graphic antialiasing
		RenderOptionNoAntiAlias =				0x0002,
		//! No bicubic interpolation
		RenderOptionNoBiCubicInterpolation=	0x0004
	};
	//! \name Flags
	//@{
	//! rendering options for error bar
	static enum EErrorBarFlag
	{
		//! relative error to lines
		ErrorBarRelative=	0x0001,
		//! horizontal error bars
		ErrorBarHorizontal=	0x0002,
		//! add shadow
		ErrorBarShadow=		0x0004
	};
	//! Surface flags
	static enum ESurfFlags
	{
		//! Draw wireframe
		SurfWireFrame=			0x0001,
		//! No color surface (use with ESurfWireFrame)
		SurfNoColorSurface=	0x0002
	};
	static enum EVectorFieldFlags
	{
		//! Constant length,
		VectorFieldConstantLength=		0x0001,
		//! No round cap
		VectorFieldNoStartCap	=		0x0002,
		//! No arrow cap
		VectorFieldNoEndCap		=		0x0004
	};
	static void GetDefaultLOGFONT(LOGFONT& lf);
public:
	/*! \brief Prepares for painting
	This function must be called before calling any painting routine. Among other things, the method does the following:
	<ul>
		<li>Resets views and bounding boxes,</li>
		<li>Prepares state stack, view stack and clip stack</li>
	</ul>
	Note that it may be override in inherited classes.
	*/
	virtual void BeginPaint(HDC hDC );
	/*! \brief Finished painting
	This function must be called after finishing painting routine. The method does the following:
	<ul>
		<li>Check that stacks are emptys (in debug mode)</li>
		<li>Flushes paint instructions,</li>
	</ul>
	Note that it may be override in inherited classes.
	*/
	virtual void EndPaint();
	virtual void AddComment(LPCTSTR str)=0;
	virtual void PushClipWorld(double llx, double lly, double urx, double ury)
    {	
		ASSERT(llx<=urx); 
		ASSERT(lly<=ury);
		m_stClips.push(m_rCurClip);
		m_rCurClip.left = WorldToBBx(llx);	m_rCurClip.width = WorldToBBAbsx(urx-llx);
		m_rCurClip.top = WorldToBBy(ury);	m_rCurClip.height = WorldToBBAbsy(ury-lly); 
	};
	/*! \brief Restore previous Clip world.
	The previous clip box is set.
	\sa PushClipWorld
	*/
	virtual void PopClipWorld(){	ASSERT(!m_stClips.empty()); m_rCurClip=m_stClips.top(); m_stClips.pop();};
	virtual void PushState()=0;
	virtual void PopState()=0;
	virtual void DrawGridHor(double llx, double urx, double lly, double ury,double dy)=0;
	virtual void DrawGridVer(double llx, double urx, double lly, double ury,double dx)=0;
	virtual void SetColor(double r, double g, double b, double a = 1) = 0;
	virtual void SetFillColor(double r, double g, double b, double a = 1) = 0;
	virtual void SetLinearGradientFill(const SPointD& point1, const SPointD& point2, const SRGBA& col1, const SRGBA& col2)=0;
	virtual void SetShadowColor(double r, double g, double b, double a = 1) = 0;
	virtual void SetLineWidth(double width) = 0;	
	virtual void SetDash(LPCTSTR dash) = 0;
	virtual void DrawRect(double llx, double lly, double urx, double ury, DWORD dwRectFlag = RectTypeFilled, SPointD sShadowSize = SPointD(5,5))=0;
	virtual void DrawArrow(double tailx, double taily, double tipx, double tipy, double tailthickness, double  headthickness, double headlength, bool filled =true)=0;
	virtual void DrawArrowAbs(double tailx, double taily, double dtipx, double dtipy, double tailthickness, double  headthickness, double headlength, bool filled =true)=0;
	virtual void DrawLine(double x1, double y1, double x2, double y2)=0;
	virtual void DrawLineStrip(const CVectorF& vX, const CVectorF& vY, DWORD eLineTypeFlag =0 , double dTension=0)=0;
	virtual void DrawStepStrip(const CVectorF& vX, const CVectorF& vY, DWORD eLineTypeFlag =0 )=0;
	virtual void DrawBandStrip(const CVectorF& vX, const CVectorF& vYBottom, const CVectorF& vYTop, DWORD eBandTypeFlag = 0, double dTension=0)=0;
	virtual void DrawMultipleLineStrip(int ns, const CVectorF& vX, const CVectorF& vY, DWORD eLineTypeFlag =0 )=0;
	virtual void DrawStock( double x0, double dx, const CVectorF& vHis, const CVectorF& vLows, const CVectorF& vOpens, const CVectorF& vCloses, const SRGBA& cDownColor, DWORD eStockTypeFlag = 0){};
	virtual void DrawErrorBars( const CVectorF& vXs,  const CVectorF& vYs,const CVectorF& vUps, const CVectorF& vDowns, double dWidth, bool bAbsolute = true, bool bVertical = true){};
	virtual void DrawCircle(double cx, double cy, double radius, DWORD eLineType = LineTypeClosed) = 0;
	virtual void DrawPolygon(double cx, double cy,  const CVectorF& vPx, const CVectorF& vPy, DWORD eLineType = LineTypeClosed) = 0;
	virtual void DrawCircleStrip(const CVectorF& vCx, const CVectorF& vCy, double radius, DWORD eLineType = LineTypeClosed)=0;
	virtual void DrawPolygonStrip(const CVectorF& vCx, const CVectorF& vCy,  const CVectorF& vPx, const CVectorF& vPy, DWORD eLineType = LineTypeClosed)=0;
	virtual void SetFont(const LOGFONT& logFont)=0;
	virtual void DrawText(double x, double y, LPCTSTR str, ETextAlignment ta = TextAlignmentLeft, double angle = 0)=0;
	virtual void DrawTextStrip(const std::vector<SPointD>& points, const std::vector<std::_tstring>& lStrings, ETextAlignment ta = TextAlignmentCenter, double angle = 0)=0;
	virtual void DrawArc(double cnx, double cny, double rn, double angle, double aperture, double rep, DWORD flags)=0;
	virtual void DrawSurf(const contour::TLattice<float>& tLattice, const CVectorF& vColor, DWORD dwFlags=0)=0;
	virtual void DrawVectorField(const contour::TLattice<float>& tLattice, const CVectorF& vVx, const CVectorF& vVy, float fScale, DWORD dwFlags=0)=0;
	virtual double BBToWorldx(double x) const=0;
	virtual double BBToWorldy(double y) const=0;
	virtual double BBToWorldAbsx(double x) const=0;
	virtual double BBToWorldAbsy(double y) const=0;
	//! Transform world x coordinate to file coordinate x
	virtual double WorldToBBx(double x) const=0;
	//! Transform world y coordinate to file coordinate y
	virtual double WorldToBBy(double y) const=0;
	//! Transform world x coordinate to file coordinate x
	virtual double WorldToBBAbsx(double x) const=0;	
	//! Transform absolute world y coordinate to file coordinate y
	virtual double WorldToBBAbsy(double y) const=0;
	virtual double NormBBoxToBBy(double y) const	{	return m_sCurBBox.screen.top - (1-y) * m_sCurBBox.screen.height;};
	virtual double NormClipBBoxToWorldy(double y) const		{	return BBToWorldy(m_rCurClip.top -(1-y) * m_rCurClip.height);};
	virtual double GetWorldClipBottom() const		{	return BBToWorldy(m_rCurClip.top-m_rCurClip.height);};
	virtual double GetWorldClipTop() const			{	return BBToWorldy(m_rCurClip.top);};
	virtual double GetBBClipBottom() const		{	return m_rCurClip.top-m_rCurClip.height;};
	virtual double GetBBClipTop() const			{	return m_rCurClip.top;};
	virtual double GetYDirectionUp() const	{	return 1;};
	
	// Saves World and screen bounding box to a stack
	virtual void PushBBox()		{	m_stBBoxes.push(m_sCurBBox);	};
	/*! \brief Restore previous view bounding box
	\sa PushBBox
	*/
	virtual void PopBBox(){	ASSERT(!m_stBBoxes.empty()); m_sCurBBox=m_stBBoxes.top(); m_stBBoxes.pop();};
	/*! \brief Sets a new clipping box and stores previous on a stack.
	\param llx Lower-left corner x coordinate (in World coornidates) 
	\param lly Lower-left corner y coordinate (in World coornidates) 
	\param urx Upper-right corner x coordinate (in World coornidates) 
	\param ury Upper-right corner y coordinate (in World coornidates) 
	A new clipping box is set. The previous is stored on a stack. All PushClipWorld call
	must be followed by a PopClipWorld cass.
	\sa PopClipWorld
	*/
	virtual void SetTextureFill(Gdiplus::Bitmap* pBitmap, const SRectD& rDestRect, ETextureWrapMode eWrapMode){};
	virtual void SetLayer(ELayer eLayer){};
	virtual ELayer GetLayer() const	{	return LayerDisabled;};
	virtual void DrawRectStrip( const CVectorF& vX0, const CVectorF& vY0, const CVectorF& vWidth, const CVectorF& vHeight, DWORD dwRectFlag = 0){};
	virtual SPointD MeasureString(LPCTSTR szString, LOGFONT lfFont);
	virtual void DrawDonnut(double cnx, double cny, double rin, double rout, double angle, double aperture, double rep, DWORD flags){};
	virtual void DrawBitmap( Gdiplus::Bitmap*  pBitmap, const SRectI& rOrigBitmap, const SRectD& rDestBitmap){};
	virtual void Rotate( double angleRad, double xOrig = 0, double yOrig = 0){};
	virtual void Scale( double xScale, double yScale, double xOrig = 0, double yOrig = 0){};
	virtual double BBToNormAbsx(double x) const	{	return x/m_sCurBBox.screen.width;	};
	virtual double BBToNormAbsy(double y) const	{	return y/m_sCurBBox.screen.height;	};
	virtual double BBToNormClipAbsx(double x) const	{	return x/m_rCurClip.width;	};
	virtual double BBToNormClipAbsy(double y) const	{	return y/m_rCurClip.height;	};
	virtual double NormBBoxToBBx(double x) const	{	return m_sCurBBox.screen.left + x * m_sCurBBox.screen.width;};
	virtual double NormBBoxToBBAbsx(double x) const	{	return x * m_sCurBBox.screen.width;};
	virtual double NormBBoxToBBAbsy(double y) const	{	return GetYDirectionUp() * y * m_sCurBBox.screen.height;};
	virtual double NormBBoxToWorldx(double x) const	{	return m_sCurBBox.world.left + x * m_sCurBBox.world.width;};
	virtual double NormBBoxToWorldy(double y) const	{	return m_sCurBBox.world.top - (1-y) * m_sCurBBox.world.height;};
	virtual double NormBBoxToWorldAbsx(double x) const	{	return x * m_sCurBBox.world.width;};
	virtual double NormBBoxToWorldAbsy(double y) const	{	return y * m_sCurBBox.world.height;};
	virtual double NormClipBBoxToWorldx(double x) const		{	return BBToWorldx(m_rCurClip.left + x * m_rCurClip.width);};
	virtual double NormClipBBoxToWorldAbsx(double x) const	{	return BBToWorldAbsx(x * m_rCurClip.width);};
	virtual double NormClipBBoxToWorldAbsy(double y) const	{	return BBToWorldAbsy(y * m_rCurClip.height);};
	virtual double NormClipBBoxToBBx(double x) const		{	return m_rCurClip.left + x * m_rCurClip.width;};
	virtual double NormClipBBoxToBBy(double y) const		{	return m_rCurClip.top +(1-y) * m_rCurClip.height;};
	virtual double NormClipBBoxToBBAbsx(double x) const		{	return x * m_rCurClip.width;};
	virtual double NormClipBBoxToBBAbsy(double y) const		{	return y * m_rCurClip.height;};
	virtual double WorldToNormAbsx(double x) const	{	return x / m_sCurBBox.world.width;	};
	virtual double WorldToNormAbsy(double y) const	{	return y / m_sCurBBox.world.height;	};
	virtual double WorldToNormClipAbsx(double x) const	{	return x / m_rCurClip.width;	};
	virtual double WorldToNormClipAbsy(double y) const	{	return y / m_rCurClip.height;	};
public:
	CGfxInterface();
	virtual ~CGfxInterface();

	void SetRenderOption(DWORD dwOption) {	m_dwRenderOption = dwOption;};	
	DWORD GetRenderOption() const {	return m_dwRenderOption;};
	void SetHDC(HDC hDC);
	HDC GetHDC() {	return m_hDC;};

	//! Sets the main bounding box: (llx,lly) and (urx,ury) are respectively the lower-left and upper-right corner of the image.
	bool SetMainBoundingBox(int llx, int lly, int urx, int ury);
	//! Set the main bounding box
	bool SetMainBoundingBox(const CRect& rect);
	//! Sets the current bounding box: (llx,lly) and (urx,ury) are respectively the lower-left and upper-right corner of the image.
	bool SetBoundingBox(int llx, int lly, int urx, int ury);
	//! Sets the bounding box: (llx,lly) and (urx,ury) are respectively the lower-left and upper-right corner of the image.
	bool SetWorldBoundingBox(double llx, double lly, double urx, double ury);

	double GetMainBBLeft() const {	return m_rMainBoundingBox.left;};
	double GetMainBBTop() const {	return m_rMainBoundingBox.top;};
	double GetMainBBRight() const {	return m_rMainBoundingBox.left+m_rMainBoundingBox.width;};
	double GetMainBBBottom() const {	return m_rMainBoundingBox.top-m_rMainBoundingBox.height;};
	double GetMainBBWidth() const {	return m_rMainBoundingBox.width;};
	double GetMainBBHeight() const {	return m_rMainBoundingBox.height;};
	
	double GetBBLeft() const {	return m_sCurBBox.screen.left;};	
	double GetBBTop() const {	return m_sCurBBox.screen.top;};
	double GetBBRight() const {	return m_sCurBBox.screen.left+m_sCurBBox.screen.width;};
	double GetBBBottom() const {	return m_sCurBBox.screen.top-m_sCurBBox.screen.height;};
	double GetBBWidth() const {	return m_sCurBBox.screen.width;};
	double GetBBHeight() const {	return m_sCurBBox.screen.height;};
	
	double GetBBClipLeft() const {	return m_rCurClip.left;};
	double GetBBClipRight() const {	return m_rCurClip.left+m_rCurClip.width;};
	double GetBBClipWidth() const {	return m_rCurClip.width;};
	double GetBBClipHeight() const {	return fabs(m_rCurClip.height);};

	double GetWorldLeft() const {	return m_sCurBBox.world.left;};
	double GetWorldTop() const {	return m_sCurBBox.world.top;};
	double GetWorldRight() const {	return m_sCurBBox.world.left+m_sCurBBox.world.width;};
	double GetWorldBottom() const {	return m_sCurBBox.world.top-m_sCurBBox.world.height;};
	double GetWorldWidth() const {	return m_sCurBBox.world.width;};
	double GetWorldHeight() const {	return m_sCurBBox.world.height;};
	
	double GetWorldClipLeft() const {	return BBToWorldx(m_rCurClip.left);};
	double GetWorldClipRight() const {	return BBToWorldx(m_rCurClip.left+m_rCurClip.width);};
	double GetWorldClipWidth() const {	return BBToWorldAbsx(m_rCurClip.width);};
	double GetWorldClipHeight() const {	return BBToWorldAbsy(m_rCurClip.height);};
	
	int CreateFontSize(HDC hDC, int points);
	double SetFontRatio(double ratio)	{ double tmp=m_dFontRatio; m_dFontRatio=ratio; return tmp;};
	double NormalizeAngle(double angle) const{		if (angle>=0) return angle - 360*((int)floor(angle)/360); else return angle + 360*((int)floor(angle)/360 +1); };

protected:
	//! main bounding box llx lly width height
	SRectI m_rMainBoundingBox;
	//! Current screen and world bounding boxes
	SBBoxState m_sCurBBox;
	//! Stack of states
	SBBoxStateStack m_stBBoxes;
	//! Current clip coordinates
	SRectD	m_rCurClip;
	//! Stack of clip coordinates
	SRectDStack m_stClips;
	//! ratio to be applied to font...
	double m_dFontRatio;
	//! render options
	DWORD m_dwRenderOption;
private:
	//! Current device context
	HDC m_hDC;
	//! has to delete dc after endpaint...
	bool m_bDeleteDC;
};

}

#endif // !defined(AFX_GFXINTERFACE_H__287E3BC9_0E37_4D0B_87B2_4EA1CEF0A76D__INCLUDED_)
